package engine.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import static org.lwjgl.opengl.EXTTextureFilterAnisotropic.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL14.*;

public class ImageUtil
{
    
    //<editor-fold defaultstate="collapsed" desc="Singleton">
    private static ImageUtil singleton;
    
    public static ImageUtil get()
    {
        if (singleton == null)
        {
            singleton = new ImageUtil();
        }
        return singleton;
    }
    //</editor-fold>
    
    private static final String FILE_PATH = "images/";
    private static final String FILE_TYPE = ".png";
    
    
    private ImageUtil()
    {
    }
    
    public BufferedImage loadImage(String fileName) 
    {
        BufferedImage image = null;
        try
        {
            image = ImageIO.read(
                new File(
                    ImageUtil.FILE_PATH + fileName + ImageUtil.FILE_TYPE
                )
            );
        }
        catch (Exception e)
        {
            System.out.println("Failure loading image: " + fileName);
            System.out.println(e);
            System.exit(1);
        }
        return image;
    }
    
    public int genGLTexture(BufferedImage image) 
    {
        int imageW = image.getWidth();
        int imageH = image.getHeight();
        byte[] byteArr = this.getByteArr(image, 0, imageW, imageH);
        ByteBuffer texImageBuffer = DataUtil.get().asByteBuffer(byteArr);
        
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        int textureID = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, textureID);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        float maxAnisotropy = glGetFloat(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
        glTexImage2D(
            GL_TEXTURE_2D, 
            0, 
            GL_RGBA, 
            imageW, 
            imageH, 
            0, 
            GL_RGBA, 
            GL_UNSIGNED_BYTE, 
            texImageBuffer
        );
        glBindTexture(GL_TEXTURE_2D, 0);
        return textureID;
    }
    
    private byte[] getByteArr(BufferedImage img, int startX, int texsW, int texsH) 
    {
        int pix, alpha, r, g, b;
        int index = 0;
        byte[] byteArr = new byte[texsH * texsW * 4];
        for (int y = texsH - 1; y >= 0; y--) // Iterations = (texW * texH), huge cost
        {
            for (int x = startX; x < (startX + texsW); x++) 
            {
                pix = img.getRGB(x, y); // Grab pixel data from the image
                alpha = (pix >> 24) & 0xFF; // Unpack pixel data from ARGB format
                r = (pix >> 16) & 0xFF;
                g = (pix >> 8) & 0xFF;
                b = pix & 0xFF;
                byteArr[index++] = (byte) r; // Pack pixel data into RGBA format
                byteArr[index++] = (byte) g;
                byteArr[index++] = (byte) b;
                byteArr[index++] = (byte) alpha;
            }
        }
        return byteArr;
    }
    
}
